package com.chenjl.exchange;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * 
 * 2016-9-6 02:49:23
 * @author chenjinlong
 */
public class ResponseFuture implements Future<Object> {
	private static final Logger logger = LoggerFactory.getLogger(ResponseFuture.class);
	
	private static final ConcurrentHashMap<Long,ResponseFuture> INVOKE_MAP = new ConcurrentHashMap<Long,ResponseFuture>();
	public static void handlerResponse(Response response) {
		logger.info("handlerResponse , response : {}",response);
		ResponseFuture responseFuture = INVOKE_MAP.get(response.getId());
		if(responseFuture==null) {
			logger.error("客户端收到Response, request不存在 , responseId : {}",response.getId());
			return;
		}
		
		try {
			responseFuture.setResponse(response);
		}
		finally {
			INVOKE_MAP.remove(response.getId());
		}
	}
	public static void clear() {
		INVOKE_MAP.clear();
	}
	
	//////////////
	private ReentrantLock lock = new ReentrantLock();
	private Condition condition = lock.newCondition();
	private volatile boolean done = false;
	private Request request;
	private Response response;

	public ResponseFuture(Request request) {
		this.request = request;
		INVOKE_MAP.put(request.getId(),this);
	}
	
	public Response getResponse() {
		return response;
	}
	public void setResponse(Response response) {
		lock.lock();
		try{
			this.response = response;
			this.done = true;
			condition.signal();
		}
		finally {
			lock.unlock();
		}
	}
	@Override
	public boolean cancel(boolean mayInterruptIfRunning) {
		INVOKE_MAP.remove(request.getId());
		return false;
	}
	@Override
	public boolean isCancelled() {
		return false;
	}
	@Override
	public boolean isDone() {
		return done;
	}
	@Override
	public Object get() throws InterruptedException, ExecutionException {
		lock.lock();
		try{
			if(!done) {
				logger.info("waiting~~");
				condition.await();
			}
		}
		finally {
			lock.unlock();
		}
		return response.getData();
	}
	@Override
	public Object get(long timeout,TimeUnit unit) throws InterruptedException,ExecutionException, TimeoutException {
		try{
			lock.lock();
			if(!done) {
				//超时不丢出异常
				condition.await(timeout,unit);
			}
			if(done) {
				return response.getData();
			}
		}
		finally {
			lock.unlock();
		}
		return null;
	}
}